This object is an enhanced subclass of ScrollView. It adds the following features:
Support for a 'top view', a view at the top of the scroll view that scrolls horizontally with the document but remains static when the document is scrolled vertically. This is useful to add column headers, rulers, etc, to a document. The top view can be added from inside of IB by connecting the topView outlet.
Support for a 'left view', a view to the left of the scroll view that scrolls vertically with the document, but remains static when the document is scrolled horizontally. This is useful for adding rulers, line numbers, etc, to a document. The left view can be added from inside of IB by connecting the leftView outlet.
Automatic support for rulers. If a topView or leftView has not been set, a call to setShowTopView:YES, setShowLeftView:YES, showRulers: or toggleRulers: will instanciate a member of rulerClass (see setRulerClass:). Depending on which ruler is called, the scrollview will try to call setHorizontal or setVertical on the new rulerClass instance. The default class is Ruler (from Draw). A ruler that supports flipping and smooth zooming is forthcoming.
Support for synchronizing other scroll views. Other ScrollViews can be made to scroll, size and zoom with respect to the docView by using the addSyncViews: methods. This is useful for ruler type views that need to exist outside of the scrollers. One synchronized view of each type can be added in IB by connecting a given ScrollView to the syncViews, horizSyncViews or vertSyncViews outlets. Be sure and connect to a ScrollView and not its content view (this can be tricky for ScrollViews without scrollers). Synchronized ScrollViews should not have scrollers of their own (but they can).
Automatic support for page up/down & left/right buttons. Simply call the method setPageUpDownButtonsVisible:YES or setPageLeftRightButtonsVisible:YES and these are added automatically. They are removed temporarily if the scroller is too small(less than an inch), if there is nothing to be scrolled or if the scrolling area is less than 2 pages.
Automatic support for zooming. Simply call the method setShowZoomButton:YES and a popup list containing zoom values will be added to the horizontal scroller. Zooming is implemented by calling zoomTo:(float)zoomX :(float)zoomY on the docView(and topView, leftView, syncViews, horizSyncViews and vertSyncViews). If the docView does not respond to this method or returns NO from this method, automatic zooming is performed by scaling the clipView by the zoom amount. The 'Set...' item in the zoom popup allows for arbitrary scaling. The 'Fit' menu item calculates the zoom value necessary to fit the docView entirely in the scrollview. The default zooming behavior tends to fail on documents that contain NXImages. Implement zoomTo:: in your custom view to explicitly scale NXImages (returning NO if you don't otherwise handle zoom).
Support for adding arbitrary views to the vertical and horizontal scrollers. This is useful for adding little gadgets like a 'goto page' control inside of the horizontal scroller. The page up/down & left/right buttons as well as the zoom button use this facility. Page left/right is assumed to be the first in the horizScrollerViews list if it exists. The zoom button is next. Other views should be added at [horizScrollerViews count]. Page up/down is assumed to be first in the vertScrollerViews list. Scroller views are temporarily removed in reverse order if the scroller is not long enough to accommodate them.
The PAScrollViewDeluxe palette allows you to create a PAScrollViewDeluxe by command clicking the 'Group in ScrollView' menu item. The code is a complete hack inside of the PAScrollViewDeluxeInspector code (at the bottom) and introduces a bug into IB that you can no longer drag the default TextObject/ScrollView in (it just disapears).
Copyright 1992. Jeff Martin. (jmartin@next.com 415-780-3833)
topView returns the current topView. If none exists, it allocates a view of ruler class, sets it to be the topView and returns it.
setTopView: places the given view inside the scrollview (inside a clip view, topClip) at the top of the scroll view at its origional hieght but at the width of the docView. It returns the oldTopView.
topViewVisible returns whether or not the topView is visible.
setTopViewVisible: will install the current topView inside a clipView on top of the docView if set to YES and will remove the existing topView if set to NO. Retiles the views, but does not call display.Returns self.
leftView, setLeftView: - query and set the "left view".
leftView returns the current leftView. If none exists, it allocates a view of ruler class, sets it to be the leftView and returns it.
setLeftView: places the given view inside the scrollview (inside a clip view, leftClip) at the left of the scroll view at its origional width but at the height of the docView. It returns the oldLeftView.
leftViewVisible, setLeftViewVisible - query & set whether leftView is visible
leftViewVisible returns whether or not the leftView is visible.
setLeftViewVisible: will install the current leftView inside a clipView on left of the docView if set to YES and will remove the existing leftView if set to NO. Retiles the views, but does not call display. Returns self.
These are convenience methods for showing/hiding/toggling top and left views as a pair. They wrap around the setTopViewVisible and setLeftViewVisible. These methods can be set to be called from menus or controls inside of InterfaceBuilder. They all return self.
If the PAScrollView deluxe is asked to show top or left views when none has been set, it attempts to allocate an instance of 'rulerClass' (assumed to be a view). If the instance responds to setHorizontal or setVertical, this will be called.
When PAScrollViewDeluxe allocates a default top/left view, it sets the top one to be of height rulerSize.height and the left one to be of width rulerSize.width. If a topView or leftView are added programatically, the rulerSize.height and rulerSize.width are set respectively.
syncViews are ScrollViews that are to be scrolled, sized and (optionally)zoomed with respect to the docViews position, size and zoom. horizSyncViews are only affected in the horizontal direction, while vertSyncViews are only affected in the vertical direction. Group a view inside of a ScrollView, disable its horizontal and vertical scrollers, and use one of the addMethods. In IB you can actually set one of each type view by setting the syncViews, horizSyncViews or vertSyncViews outlet to a ScrollView. It will be added to the list when the outlets are set.
The syncViews, horizSyncViews and vertSyncViews methods return the list of the views that are currently being syncronized in the respective direction(can be NULL if there are none).
addSyncView:at:, addHorizSyncView:at: and addVertSyncView:at: add scrollviews to be synchronized in the respective direction at the given location in the list(use [[myPASV syncViews] count] to add to end). Returns self.
removeSyncView:, removeHorizSyncView:, removeVertSyncView: remove the given view from its respective list by calling removeSyncAt: with the view's index.
removeSyncViewAt:, removeHorizSyncViewAt: and removeVertSyncViewAt: remove ScrollViews from the respective list of syncronized ScrollViews. Returns self.
ScrollerViews are views embedded inside of the vertical or horizontal scrollers. The are frequently simple controls like a "Goto Page:" control. In fact the page up/down & left/right buttons as well as the zoomButton are horizScrollerViews (assumed to be at 0 and 1 respectively if they exist).When added these views are sized to fit into the scroller(ie, horizontal scroller views are constrained to the horizontal scroller's height).
The horizScrollerViews and vertScrollerViews methods return the list of the views that are currently in the respective scroller (can be NULL if there are none).
addHorizScrollerView:at: and addVertScrollerView:at: add a view to their respective list at the given location(use [[myPASV vertSyncViews] count] to add to end). They returns self.
removeHorizScrollerView: and removeVertScrollerView: removes the given view from the respective scroller list. Returns self.
removeHorizScrollerViewAt: and removeVertScrollerViewAt: removes the view at the given location from the respective scroller list. Returns self.
These methods return pointers to the matrices that contain the up/down & left/right buttons. They are loaded in at init time from PAScrollViewDeluxe.nib.
These methods query and set whether the respective button set is visible.
The setButtonsVisible method calls the respective add or remove scrollerView method with the 'at' value equal to zero.
The needPageButtons methods return whether the page buttons are actually needed (ie, if the docView is smaller than the contentView or the scrollable area is less than 2 pages, the buttons are not needed).
This method is the target to all of the page up/down/left/right buttons. Based on the tags, it scrolls the visible rect by its extents minus the page overlap (pageContext) in the respective direction. Returns self.
These methods query and set whether the zoom button is visible.
setZoomButtonVisible: either adds the zoomButton to the vert scroller via - addHorizScrollerView: or removes via removeHorizScrollerView. Returns self.
This method is called by the zoomButton's popUpList to get the zoom amount. It reads the title and converts it to a scale (special cased for 'Set...' and 'Size To Fit'). Calls zoomTo::.
This method tries to call zoomTo:: on the docView and all of the accessory views (topView, leftView, syncViews, horizSyncViews, vertSyncViews) with the given scale (1 is full size). If the views implement zoomTo:: and actually do the zoom, they should return YES. If they just implement zoomTo:: to get notification of a zoom or to scale dependent pieces(like NXImages), they should return NO. If zoomTo:: is not implemented or returns NO, automatic scaling takes place(on the ClipView).
This method is called automatically whenever any of the clipView subviews are scrolled. We intercept it so that we can perform the scroll on all of the dependant views(topView, leftView, syncViews, horizSyncViews & vertSyncViews). Returns Self.
This method sets the first clipView so that it is viewing as much of the same rect that the withClipView is viewing as possible. It figures out this rect in the withClipView, corrects for coordinate system differences and flippedness and does a rawScroll in the given clipView.
The horizontally and vertically flags allow the synchronization to be constrained to a particular direction.
This method is called within scrollClip:to: to synchronize the various parts of the ScrollView (rulers, etc). You will probably never call it directly. Returns self.
This method is called to adjust the scrollers when there has been a change to the docView (it is called automatically durring autoscroll or when the docView is resized). We override it so that we can add or remove the page buttons if necessary. Returns self.
This method is called automatically whenever the document changes its frame size. We override it so that we can grow the dependent views respectively (topView, leftView, syncView, horizSyncView, vertSyncViews).
This method is where the real work of adding all of the subviews to the scrollview happens. It simply does a divide rect on the various parts and sets the origional parts to the diminished rect and the new parts to the new rect. Does not display. Returns self.
This method tiles the views in the scrollers. Views are added to the scroller in the order they are encountered in their respective list. If they don't leave at least an inch for the scroller if added, they are not added.
I had to pull this code out of the tile method because the scrollers need to be retiled occasionally after a reflectScroll (to see if the page buttons go away). Since tile indirectly causes a reflectScroll, it cannot be called from within reflectScroll. Returns self.